home *** CD-ROM | disk | FTP | other *** search
/ EuroCD 3 / EuroCD 3.iso / Programming / Python1.4_Source / Lib / cmp.py < prev    next >
Text File  |  1998-06-24  |  2KB  |  62 lines

  1. # Module 'cmp'
  2.  
  3. # Efficiently compare files, boolean outcome only (equal / not equal).
  4.  
  5. # Tricks (used in this order):
  6. #    - Files with identical type, size & mtime are assumed to be clones
  7. #    - Files with different type or size cannot be identical
  8. #    - We keep a cache of outcomes of earlier comparisons
  9. #    - We don't fork a process to run 'cmp' but read the files ourselves
  10.  
  11. import os
  12.  
  13. cache = {}
  14.  
  15. def cmp(f1, f2): # Compare two files, use the cache if possible.
  16.     # Return 1 for identical files, 0 for different.
  17.     # Raise exceptions if either file could not be statted, read, etc.
  18.     s1, s2 = sig(os.stat(f1)), sig(os.stat(f2))
  19.     if s1[0] <> 8 or s2[0] <> 8:
  20.         # Either is a not a plain file -- always report as different
  21.         return 0
  22.     if s1 == s2:
  23.         # type, size & mtime match -- report same
  24.         return 1
  25.     if s1[:2] <> s2[:2]: # Types or sizes differ, don't bother
  26.         # types or sizes differ -- report different
  27.         return 0
  28.     # same type and size -- look in the cache
  29.     key = f1 + ' ' + f2
  30.     try:
  31.         cs1, cs2, outcome = cache[key]
  32.         # cache hit
  33.         if s1 == cs1 and s2 == cs2:
  34.             # cached signatures match
  35.             return outcome
  36.         # stale cached signature(s)
  37.     except KeyError:
  38.         # cache miss
  39.         pass
  40.     # really compare
  41.     outcome = do_cmp(f1, f2)
  42.     cache[key] = s1, s2, outcome
  43.     return outcome
  44.  
  45. def sig(st): # Return signature (i.e., type, size, mtime) from raw stat data
  46.     # 0-5: st_mode, st_ino, st_dev, st_nlink, st_uid, st_gid
  47.     # 6-9: st_size, st_atime, st_mtime, st_ctime
  48.     type = st[0] / 4096
  49.     size = st[6]
  50.     mtime = st[8]
  51.     return type, size, mtime
  52.  
  53. def do_cmp(f1, f2): # Compare two files, really
  54.     bufsize = 8*1024 # Could be tuned
  55.     fp1 = open(f1, 'r')
  56.     fp2 = open(f2, 'r')
  57.     while 1:
  58.         b1 = fp1.read(bufsize)
  59.         b2 = fp2.read(bufsize)
  60.         if b1 <> b2: return 0
  61.         if not b1: return 1
  62.